<?php

namespace app\admin\controller\litestore;

use app\admin\library\Auth;
use app\common\controller\Backend;
use app\admin\model\litestore\Litestorespec as SpecModel;
use app\admin\model\litestore\Litestoregoodsspec as GoodsSpecModel;
use app\admin\model\litestore\Litestorespecvalue as SpecValueModel;
use Exception;
use fast\Tree;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use think\Db;
use think\db\exception\BindParamException;
use think\exception\PDOException;

/**
 * 
 *
 * @icon fa fa-circle-o
 */
class Litestoregoods extends Backend
{
    private $SpecModel;
    private $SpecValueModel;
    /**
     * Litestoregoods模型对象
     * @var \app\admin\model\Litestoregoods
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();

        $this->model = model('app\common\model\LitestoreCategory');
        $tree = Tree::instance();
        $tree->init(collection($this->model->order('weigh desc,id desc')->select())->toArray(), 'pid');
        $this->categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name');
        $categorydata = [0 => ['type' => 'all', 'name' => __('None')]];
        foreach ($this->categorylist as $k => $v) {
            $categorydata[$v['id']] = $v;
        }
        $this->view->assign("parentList", $categorydata);

        $this->SpecModel = new SpecModel;
        $this->SpecValueModel = new SpecValueModel;

        $this->model = new \app\admin\model\litestore\Litestoregoods;
        $this->view->assign("flagList", $this->model->getFlagList());
        $this->view->assign("specTypeList", $this->model->getSpecTypeList());
        $this->view->assign("deductStockTypeList", $this->model->getDeductStockTypeList());
        $this->view->assign("goodsStatusList", $this->model->getGoodsStatusList());
        $this->view->assign("isDeleteList", $this->model->getIsDeleteList());

        $this->view->assign("spec_attr", '');
        $this->view->assign("spec_list", '');
    }
    
    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */
    

    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isAjax())
        {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField'))
            {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $total = $this->model
                    ->with(['category','spec'])
                    ->where("is_delete='0'")
                    ->where($where)
                    ->order($sort, $order)
                    ->count();

            $list = $this->model
                    ->with(['category','spec'])
                    ->where("is_delete='0'")
                    ->where($where)
                    ->order($sort, $order)
                    ->limit($offset, $limit)
                    ->select();

            foreach ($list as $k => $row) {
                $row->getRelation('category')->visible(['name']);
                $list[$k]['name_p'] = get_parent_all($row->category_id);
                $images = $row['images'];
                unset($list[$k]['images']);
                $list[$k]['images'] = cdnurl(explode(",",$images)[0], true);
                $list[$k]['goods_price'] = $row['spec'][0]['goods_price'];
                $list[$k]['line_price'] = $row['spec'][0]['line_price'];
                $list[$k]['cost_price'] = $row['spec'][0]['cost_price'];
                unset($list[$k]['spec']);
            }
            $list = collection($list)->toArray();
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }
        return $this->view->fetch();
    }

    public function addSpec($spec_name, $spec_value){
         // 判断规格组是否存在
        if (!$specId = $this->SpecModel->getSpecIdByName($spec_name)) {
            // 新增规格组and规则值
            if ($this->SpecModel->add($spec_name)
                && $this->SpecValueModel->add($this->SpecModel['id'], $spec_value))
                return $this->success('', '', [
                    'spec_id' => (int)$this->SpecModel['id'],
                    'spec_value_id' => (int)$this->SpecValueModel['id'],
                ]);
            return $this->error();
        }
        //return ;
        // 判断规格值是否存在
        if ($specValueId = $this->SpecValueModel->getSpecValueIdByName($specId, $spec_value)) {
            return $this->success('', '', [
                'spec_id' => (int)$specId,
                'spec_value_id' => (int)$specValueId,
            ]);
        }
        // 添加规则值
        if ($this->SpecValueModel->add($specId, $spec_value))
            return $this->success('', '', [
                'spec_id' => (int)$specId,
                'spec_value_id' => (int)$this->SpecValueModel['id'],
            ]);
        return $this->error();
    }


    /**
     * 添加规格值
     */
    public function addSpecValue($spec_id, $spec_value)
    {
        // 判断规格值是否存在
        if ($specValueId = $this->SpecValueModel->getSpecValueIdByName($spec_id, $spec_value)) {
            return $this->success('', '', [
                'spec_value_id' => (int)$specValueId,
            ]);
        }
        // 添加规则值
        if ($this->SpecValueModel->add($spec_id, $spec_value))
            return $this->success('', '', [
                'spec_value_id' => (int)$this->SpecValueModel['id'],
            ]);
        return $this->error();
    }

    /**
     * 添加
     */
    public function add()
    {
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if(empty($params['category_id'])){
                $this->error(__('Please select a classification'));
            }
            if ($params) {
                if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                    $params[$this->dataLimitField] = $this->auth->id;
                }
                try {
                    //是否采用模型验证
                    if ($this->modelValidate) {
                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
                        $this->model->validate($validate);
                    }
                    $result = $this->model->allowField(true)->save($params);
                    if ($result !== false) {
                        //成功之后 存储商品规格
                        $spec_many_params = $this->request->post("spec_many/a");
                        $this->model->addGoodsSpec($params,$spec_many_params,$this->request->post("spec/a"));
                        $this->success();
                    } else {
                        $this->error($this->model->getError());
                    }
                } catch (\think\exception\PDOException $e) {
                    $this->error($e->getMessage());
                } catch (\think\Exception $e) {
                    $this->error($e->getMessage());
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        return $this->view->fetch();
    }

    /**
     * 删除(更改为软删除)
     */
    public function del($ids = "")
    {
        if ($ids) {
            $pk = $this->model->getPk();
            $adminIds = $this->getDataLimitAdminIds();
            if (is_array($adminIds)) {
                $count = $this->model->where($this->dataLimitField, 'in', $adminIds);
            }
            $list = $this->model->where($pk, 'in', $ids)->select();
            $count = 0;
            foreach ($list as $k => $v) {
                // 删除商品sku（现在是软删除，软删除不删除sku）
//                $v->removesku();

                $count += $v->where('goods_id',$v->goods_id)->update(['is_delete'=>1]);
            }
            //删除博主商品库中的商品
            \think\Db::name('user_goods')->where('goods_id','in',$ids)->update(['deletetime'=>time()]);

            if ($count) {
                $this->success();
            } else {
                $this->error(__('No rows were deleted'));
            }
        }
        $this->error(__('Parameter %s can not be empty', 'ids'));
    }

    /**
     * 编辑
     */
    public function edit($ids = NULL)
    {
        $row = $this->model->get($ids, ['specRel', 'spec', 'spec_rel.spec']);
        if (!$row)
            $this->error(__('No Results were found'));
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            if (!in_array($row[$this->dataLimitField], $adminIds)) {
                $this->error(__('You have no permission'));
            }
        }
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                if(empty($params['category_id'])){
                    $this->error(__('Please select a classification'));
                }
                try {
                    //是否采用模型验证
                    if ($this->modelValidate) {
                        $name = basename(str_replace('\\', '/', get_class($this->model)));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
                        $row->validate($validate);
                    }
                    $result = $row->allowField(true)->save($params);
                    if ($result !== false) {
                        //成功之后 存储商品规格
                        $spec_many_params = $this->request->post("spec_many/a");
                        $row->addGoodsSpec($params,$spec_many_params,$this->request->post("spec/a"), true);
                        $this->success();
                    } else {
                        $this->error($row->getError());
                    }
                } catch (\think\exception\PDOException $e) {
                    $this->error($e->getMessage());
                } catch (\think\Exception $e) {
                    $this->error($e->getMessage());
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        // 多规格信息
        $specData = 'null';
        if ($row['spec_type'] === '20'){
            $specData = json_encode($this->model->getManySpecData($row['spec_rel'], $row['spec']));
        }
        $row['specData'] = $specData;
        $this->view->assign("row", $row);
        return $this->view->fetch();
    }

    /**
     * 选择表格-商品
     */
    public function select()
    {
        if ($this->request->isAjax()) {
            return $this->index();
        }
        return $this->view->fetch();
    }

    /**
     * 选择表格-商品规格
     */
    public function select_sku()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isAjax())
        {
            $this->model = new GoodsSpecModel();
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $total = $this->model
                ->with(['goods'])
                ->where("is_delete='0'")
                ->where($where)
                ->order($sort, $order)
                ->count();

            $list = $this->model
                ->with(['goods'])
                ->where("is_delete='0'")
                ->where($where)
                ->order($sort, $order)
                ->limit($offset, $limit)
                ->select();

            foreach ($list as $k => $row) {
                $images = $row['goods']['images'];
                $list[$k]['images'] = cdnurl(explode(",",$images)[0], true);
                $spec_sku_ids = explode('_',$row['spec_sku_id']);
                $sku = $this->SpecValueModel->all($spec_sku_ids,['spec']);
                $sku_text = '';
                foreach (object2array($sku) as $kk=>$vv){
                    $sku_text .= $vv['spec']['spec_name'].':'.$vv['spec_value'].';';
                }
                $list[$k]['sku_text'] = $sku_text;
            }
            $list = collection($list)->toArray();
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }
        return $this->view->fetch();
    }

    /**
     * 数据导出
     */
    public function export(){

        list($where, $sort, $order, $offset, $limit) = $this->buildparams();

        //查询所有规格
        $spec_value = \think\DB::name('litestore_spec_value')->select();
        $spec_value = array_column($spec_value,null,'id');

        $list = $this->model
            ->with(['category','spec'])
            ->where("is_delete='0'")
            ->where($where)
            ->order('goods_id desc')
            ->paginate($limit);

        $list=$list->toArray();
//        halt($list);

        # 数据填充
        $new_data = [];
        foreach ($list['data'] as $k => $v) {
            $category_name = $v['category']['name'];
            $p_category = Db::name('litestore_category')->where('id',$v['category']['pid'])->find();
            if($p_category){
                $category_name = $p_category['name'].'-'.$category_name;
            }

            $images = explode(",",$v['images']);
            foreach ($images as $ik=>$iv){
                $images[$ik] = cdnurl($iv, true);
            }
            foreach($v['spec'] as $kk=>$vv){
                $arr = [
                    $v['goods_id'],
                    $category_name,
                    $v['goods_name'],
                    $v['content'],
                    $v['flag'],
                    $v['weight'],
                    $v['long'],
                    $v['wide'],
                    $v['high'],
                    $vv['goods_spec_id'],
                ];
                if($v['spec_type'] == 20){
                    $spec_sku_ids = explode("_",$vv['spec_sku_id']);
                    if(count($spec_sku_ids) == 1){
                        array_push($arr,$spec_value[$spec_sku_ids[0]]['spec_value'],'');
                    }elseif(count($spec_sku_ids) == 2){
                        array_push($arr,$spec_value[$spec_sku_ids[0]]['spec_value'],$spec_value[$spec_sku_ids[1]]['spec_value']);
                    }
                }else{
                    array_push($arr,'','');
                }
                if($vv['spec_image']){
                    $spec_image = cdnurl($vv['spec_image'],true);
                }else{
                    $spec_image = '';
                }
                array_push($arr,$spec_image,$vv['goods_price'],$vv['line_price'],$vv['cost_price'],$vv['stock_num']);
                foreach ($images as $k3=>$v3){
                    array_push($arr,$v3);
                }
                $new_data[] = $arr;

            }
        }
        $sheetHeaderb=['Goods_id','Category','Product Name','Product Description','Flag(hot,recommend)',
            'Parcel Weight(lb)', 'Parcel Length(inch)', 'Parcel Width(inch)','Parcel Height(inch)','Goods_spec_id',
            'Variation 1 (Colour)','Variation 2 (Size)','Image of Variation 1','Retail Price (Local Currency)','Line Price','Cost Price','Stock Num',
            'Main Product Image','Product Image 2','Product Image 3','Product Image 4','Product Image 5',
            'Product Image 6','Product Image 7','Product Image 8'];
        export_xlsx($sheetHeaderb,$new_data);
    }

    /**
     * 导入
     */
    public function import()
    {
        $file = $this->request->request('file');
        if (!$file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH .  'public' .  $file;
        if (!is_file($filePath)) {
            $this->error(__('No results were found'));
        }
        //实例化reader
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
            $this->error(__('Unknown data format'));
        }
        if ($ext === 'csv') {
            $file = fopen($filePath, 'r');
            $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
            $fp = fopen($filePath, "w");
            $n = 0;
            while ($line = fgets($file)) {
                $line = rtrim($line, "\n\r\0");
                $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
                if ($encoding != 'utf-8') {
                    $line = mb_convert_encoding($line, 'utf-8', $encoding);
                }
                if ($n == 0 || preg_match('/^".*"$/', $line)) {
                    fwrite($fp, $line . "\n");
                } else {
                    fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
                }
                $n++;
            }
            fclose($file) || fclose($fp);

            $reader = new Csv();
        } elseif ($ext === 'xls') {
            $reader = new Xls();
        } else {
            $reader = new Xlsx();
        }

        //加载文件
        $insert = [];
        try {
            if (!$PHPExcel = $reader->load($filePath)) {
                $this->error(__('Unknown data format'));
            }
            $currentSheet = $PHPExcel->getSheet(0);  //读取文件中的第一个工作表
            $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号

            $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
            $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
            for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $val = trim($val);
                    $fields[] = $val;
                }
            }
            for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
                $values = [];
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $val = trim($val);
                    $values[] = is_null($val) ? '' : $val;
                }
                $row = [];
                $temp = array_combine($fields, $values);
                foreach ($temp as $k => $v) {
                    if ($k !== '') {
                        $row[$k] = $v;
                    }
                }
                if ($row) {
//                  判断表中项目名称是否存在，存在更新，不存在添加
//                    $tableData = $this->model->where('goods_name',$row['Product Name'])->find();
//                    if(empty($tableData)){
                        $insert[] = $row;
//                    }
                }
            }
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }

        if (!$insert) {
            $this->error(__('No rows were updated'));
        }
        //相同的商品名称归为一个商品
        $new_info = [];
        foreach ($insert as $k=>$v){
            $new_info[$v['Product Name']][] = $v;
        }
//        halt($new_info);

        try {
            foreach ($new_info as $k=>$goods){
//                halt($goods);
                if(count($goods) == 1){
                    if(empty($goods[0]['Variation 1 (Colour)'])){
                        $spec_type = '10';
                    }else{
                        $spec_type = '20';
                    }
                }else{
                    $spec_type = '20';
                }

                if($goods[0]['Category']){
                    $categorys = explode('-',$goods[0]['Category']);
                    $category_name = count($categorys) == 2 ? $categorys[1] : $categorys[0] ;
                    $category = Db::name('litestore_category')->where('name',$category_name)->find();
                    if($category){
                        $category_id = $category['id'];
                    }else{
                        exception($goods[0]['Product Name'].'---Category does not exist');
                    }
                }else{
                    exception($goods[0]['Product Name'].'---Category cannot be empty');
                }
                $goods_info = [];
                $add_goods = [];
                $edit_goods = [];
                $add_goods_sku = [];
                $edit_goods_sku = [];
                foreach ($goods as $kk=>$vv){
//                    halt($vv);
                    if($kk === 0){
                        $images = [
                            $vv['Main Product Image'],
                            $vv['Product Image 2'],
                            $vv['Product Image 3'],
                            $vv['Product Image 4'],
                            $vv['Product Image 5'],
                            $vv['Product Image 6'],
                            $vv['Product Image 7'],
                            $vv['Product Image 8'],
                        ];
                        $flag = $vv['Flag(hot,recommend)'];
                        if($flag){
                            $flag = explode(',',$flag);
                            $flag = implode(',',$flag);
                        }

                        $goods_info['goods_name'] = $vv['Product Name'];
                        $goods_info['category_id'] = $category_id;
                        $goods_info['images'] = implode(',',$images);
                        $goods_info['spec_type'] = $spec_type;
                        $goods_info['content'] = $vv['Product Description'];
                        $goods_info['long'] = $vv['Parcel Length(inch)'];
                        $goods_info['wide'] = $vv['Parcel Width(inch)'];
                        $goods_info['high'] = $vv['Parcel Height(inch)'];
                        $goods_info['weight'] = $vv['Parcel Weight(lb)'];
                        $goods_info['flag'] = $flag;

                        if(empty($vv['Goods_id'])){
                            $add_goods = $goods_info;
                        }else{
                            $goods_info['goods_id'] = $vv['Goods_id'];
                            $edit_goods = $goods_info;
                        }
                    }
                    if(empty($vv['Goods_id']) || empty($vv['Goods_spec_id'])){
                        $add_goods_sku[$kk]['spec_value'] = $vv['Variation 1 (Colour)'];
                        $add_goods_sku[$kk]['spec_value2'] = $vv['Variation 2 (Size)'];
                        $add_goods_sku[$kk]['spec_image'] = $vv['Image of Variation 1'];
                        $add_goods_sku[$kk]['goods_price'] = $vv['Retail Price (Local Currency)'];
                        $add_goods_sku[$kk]['line_price'] = $vv['Line Price'];
                        $add_goods_sku[$kk]['cost_price'] = $vv['Cost Price'];
                        $add_goods_sku[$kk]['stock_num'] = $vv['Stock Num'];
                    }else{
                        $edit_goods_sku[$kk]['goods_spec_id'] = $vv['Goods_spec_id'];
                        $edit_goods_sku[$kk]['spec_image'] = $vv['Image of Variation 1'];
                        $edit_goods_sku[$kk]['goods_price'] = $vv['Retail Price (Local Currency)'];
                        $edit_goods_sku[$kk]['line_price'] = $vv['Line Price'];
                        $edit_goods_sku[$kk]['cost_price'] = $vv['Cost Price'];
                        $edit_goods_sku[$kk]['stock_num'] = $vv['Stock Num'];
                    }
                }

                Db::startTrans();
                try {
                    //建商品、建规格、建SKU
                    $goodsmodel = new \app\admin\model\litestore\Litestoregoods;
                    if(!empty($add_goods)){
                        $result = $goodsmodel->save($add_goods);//新增
                        if ($result !== false) {
                            //成功之后 存储商品规格
                            $goodsmodel->importGoodsSpec($goods_info,$add_goods_sku);
                        }
                    }else{
                        $result = $goodsmodel->update($edit_goods);//更新
                        if(!empty($add_goods_sku)){
                            //成功之后 存储商品规格
                            $mm = $goodsmodel->get(['goods_id'=>$edit_goods['goods_id']]);
                            $mm->importGoodsSpec($goods_info,$add_goods_sku);
                        }
                        if(!empty($edit_goods_sku)){
                            $GoodsSpecModel = new GoodsSpecModel();
                            $GoodsSpecModel->saveAll($edit_goods_sku);
                        }
                    }

                    Db::commit();
                } catch (PDOException|Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }

            }

        } catch (PDOException $exception) {
            $msg = $exception->getMessage();
            if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $msg, $matches)) {
                $msg = "导入失败，包含【{$matches[1]}】的记录已存在";
            };
            $this->error($msg);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }

        $this->success();
    }


}
